home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Graphics 2D / Thumbnail Test / Thumbnail.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  16.5 KB  |  611 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        Thumbnail.c
  3.  
  4.     Contains:    Sample to demonstrate using the Picture Utilities Package
  5.     
  6.                 The guts of this is in the window creation function: DoCreateWindow( PicHandle thePicture )
  7.     
  8.                 DoCreateWindow is passed a picture handle and if the global gUsePictPalette is set it
  9.                 will use the pict utils package (PUP) to get the color table stored in the pict.  You could 
  10.                 this source to sample direct color images, but to keep things as clear as possible this
  11.                 application only deals with 8 bit images.
  12.     
  13.                 We use the PUP to get the color table for the image.  This is passed into NewGWorld and it
  14.                 is also used to create a palette that is attached to the window.
  15.     
  16.                 Note that we use PUP to sample the image that was stored in the file.  We interrogate a
  17.                 PicHandle read directly from the file.  There are also routines for sampling PixMaps,
  18.                 but dont forget that if you are in an indexed color environment, and you sample a PixMap, 
  19.                 if you didnt set up the color environment when your first created the PixMap, the colors
  20.                 may not be as you expect.  
  21.                 
  22.                 To see an example of this there are two 8-bit images included with this snippet.
  23.                 One is a spectral ramp, the other a green/brow ramp.  Both have approx 120 or so colors.
  24.                 to see an example of what PUP may report if you didnt set the colors for a window up
  25.                 properly before displaying open one of the files with the "use picture palette" item 
  26.                 from the palette menu toggled off.
  27.     
  28.                 in this case it will use the "wrong" set of colors to try to draw the image (it just uses
  29.                 what ever the default system color table is).  If you get PUP to sample (by toggling on
  30.                 the "use picture palette" item from the palette menu the picture is rendered correctly.
  31.  
  32.     Written by: NT    
  33.  
  34.     Copyright:    Copyright © 1994-1999 by Apple Computer, Inc., All Rights Reserved.
  35.  
  36.                 You may incorporate this Apple sample source code into your program(s) without
  37.                 restriction. This Apple sample source code has been provided "AS IS" and the
  38.                 responsibility for its operation is yours. You are not permitted to redistribute
  39.                 this Apple sample source code as "Apple sample source code" after having made
  40.                 changes. If you're going to re-distribute the source, we require that you make
  41.                 it clear in the source that the code was descended from Apple sample source
  42.                 code, but that you've made changes.
  43.  
  44.     Change History (most recent first):
  45.                 08/2000        JM                Carbonized, non-Carbon code is commented out
  46.                                             for demonstration purposes.
  47.                 7/14/1999    KG                Updated for Metrowerks Codewarror Pro 2.1
  48.                 
  49.  
  50. */
  51.  
  52. /* Constant Declarations */
  53. #include "CarbonPrefix.h"
  54. #include <menus.h>
  55. #include <PictUtils.h>
  56. #include <QDOffScreen.h>
  57. #include <Fonts.h>
  58. #include <Windows.h>
  59. #include <Menus.h>
  60. #include <TextEdit.h>
  61. #include <Dialogs.h>
  62. #include <DiskInit.h>
  63. //#include <StandardFile.h>
  64. #include <Navigation.h>
  65. #include <Devices.h>
  66.  
  67.  
  68. #define    WWIDTH        470
  69. #define    WHEIGHT        330
  70.  
  71. //#define WLEFT        (((screenBits.bounds.right - screenBits.bounds.left) - WWIDTH) / 2)
  72. //#define WTOP        (((screenBits.bounds.bottom - screenBits.bounds.top) - WHEIGHT) / 2)
  73.  
  74. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  75. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  76.  
  77.  
  78.  
  79. enum {
  80.     mApple = 128,
  81.     mFile,
  82.     mPalette,
  83.     mTest
  84. } ;
  85.  
  86. enum {
  87.     iAbout = 1
  88. } ;
  89. enum {
  90.     iOpen = 1,
  91.     iClose,
  92.     iUnused1,
  93.     iQuit = 4
  94. } ;
  95.  
  96. enum {
  97.     iUsePictPalette = 1
  98. } ;
  99.  
  100. static Boolean gQuitFlag = false ;
  101.  Point gStaggerPos = {50,50} ;
  102. static Boolean gUsePictPalette = false ;
  103.  
  104. // function prototypes
  105.  
  106. void InitToolbox( void ) ;
  107. void MainEventLoop( void ) ;
  108. void HandleKeyPress(EventRecord *event) ;
  109. void HandleOSEvent(EventRecord *event) ;
  110. void HandleMenuCommand(long menuResult) ;
  111. PicHandle DoReadPICT( short theRef, OSErr *theErr ) ;
  112. OSErr DoCreateWindow( PicHandle thePicture ) ;
  113. void AdjustMenus( void ) ;
  114.  
  115.  
  116. const RGBColor    kRGBBlack = {0, 0, 0};
  117. const RGBColor    kRGBWhite = {0xFFFF, 0xFFFF, 0xFFFF};
  118.  
  119.  
  120. void main()
  121. {
  122.     InitToolbox() ;
  123.     
  124.     MainEventLoop();
  125. }
  126.  
  127.  
  128.  
  129. void InitToolbox()
  130. {
  131.     Handle        menuBar = nil;
  132.  
  133.     // Most InitSomething calls are automatic in carbon
  134.     // Only InitCursor is still called when initializing the toolbox
  135.     //InitGraf((Ptr) &qd.thePort);
  136.     //InitFonts();
  137.     //InitWindows();
  138.     //InitMenus();
  139.     //TEInit();
  140.     //InitDialogs(0L);
  141.     InitCursor();
  142.  
  143.     // initialize application globals
  144.     
  145.     gQuitFlag = false;
  146.     
  147.     
  148.     menuBar = GetNewMBar(128);                // Read menus into menu bar, MBAR res id is 128
  149.     
  150.     if ( menuBar == nil )
  151.          ExitToShell();                        // if we dont have it then quit - your app 
  152.                                              // needs a dialog here
  153.  
  154.     SetMenuBar(menuBar);                    // Install menus
  155.     DisposeHandle(menuBar);
  156.     
  157.     //AppendResMenu(GetMenuHandle(mApple), 'DRVR');    // Add DA names to Apple menu, ID 128
  158.  
  159.     DrawMenuBar();
  160. }
  161.  
  162.  
  163. void MainEventLoop()
  164. {
  165.     EventRecord     event;
  166.     WindowPtr       window;
  167.     short           thePart;
  168.     Rect            screenRect, tempRect;
  169.     Point            aPoint = {100, 100};
  170.     GWorldPtr        theNewWorld ;
  171.     PixMapHandle    offPixMap ;
  172.     GrafPtr            oldPort ;
  173.  
  174.     while( !gQuitFlag )
  175.     {
  176.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  177.         {
  178.             AdjustMenus() ;
  179.  
  180.             switch (event.what) {
  181.                 case mouseDown:
  182.                 
  183.                     thePart = FindWindow( event.where, &window );
  184.                     
  185.                     switch( thePart ) {
  186.                         case inMenuBar: 
  187.                             HandleMenuCommand(MenuSelect(event.where));
  188.                             break;
  189.                         
  190.                         case inDrag:
  191.                     
  192.                             //screenRect = (**GetGrayRgn()).rgnBBox;
  193.                             GetRegionBounds ( GetGrayRgn(), &screenRect );
  194.                             DragWindow( window, event.where, &screenRect );
  195.                             break ;
  196.                     
  197.                         case inContent:
  198.                     
  199.                             if (window != FrontWindow())
  200.                                 SelectWindow( window );
  201.                             break ;
  202.                     
  203.                         case inGoAway:
  204.                             if (TrackGoAway( window, event.where )) {
  205.                                 DisposeWindow ( window );
  206.                             }
  207.                             break ;
  208.                             
  209.                         default:
  210.                             break ;
  211.                     }
  212.                     break ;
  213.                             
  214.                         
  215.                 case updateEvt:
  216.                 
  217.                     window = (WindowPtr)event.message;
  218.                     GetPort(&oldPort ) ;    
  219.                     //SetPort( window );
  220.                     SetPortWindowPort ( window );
  221.                     
  222.                     BeginUpdate( window );
  223.                     
  224.                     // get the GWorld from the window refcon
  225.                     theNewWorld = (GWorldPtr)GetWRefCon ( window );
  226.                     offPixMap = GetGWorldPixMap( theNewWorld ) ;
  227.                     (void) LockPixels( offPixMap ) ;
  228.                     /*CopyBits( &((GrafPtr)theNewWorld)->portBits,
  229.                               &window->portBits,
  230.                               &window->portRect,
  231.                               &window->portRect,
  232.                               srcCopy,
  233.                               nil ) ;*/
  234.                     CopyBits(     GetPortBitMapForCopyBits(theNewWorld),
  235.                                 GetPortBitMapForCopyBits(GetWindowPort(window)),
  236.                                 GetPortBounds(GetWindowPort(window), &tempRect),
  237.                                 GetPortBounds(GetWindowPort(window), &tempRect),
  238.                                 srcCopy,
  239.                                 nil );
  240.  
  241.  
  242.                     (void) UnlockPixels( offPixMap ) ;
  243.  
  244.                     EndUpdate( window );
  245.                     SetPort( oldPort ) ;
  246.                     break ;
  247.                     
  248.                 case keyDown:
  249.                 case autoKey:
  250.                     HandleKeyPress(&event);
  251.                     break;
  252.                     
  253.                 case diskEvt:
  254.                     /*if ( HiWrd(event.message) != noErr ) 
  255.                         (void) DIBadMount(aPoint, event.message);*/
  256.                     break;
  257.                     
  258.                 case osEvt:
  259.                 case activateEvt:
  260.                     break;
  261.  
  262.  
  263.             }
  264.         }
  265.     }
  266. }
  267.  
  268.  
  269. void HandleKeyPress(EventRecord *event)
  270. {
  271.     char    key;
  272.  
  273.     key = event->message & charCodeMask;
  274.     
  275.     // just check to see if we want to quit...
  276.     
  277.     if ( event->modifiers & cmdKey ) {        /* Command key down? */
  278.         HandleMenuCommand(MenuKey(key));
  279.     } 
  280. }
  281.  
  282.  
  283. void HandleMenuCommand(long menuResult)
  284. {
  285.     short        menuID;
  286.     short        menuItem;
  287.     //Str255        daName;    // not needed after carbonization
  288.     DialogPtr    theDialog ; 
  289.     short        itemHit ;
  290.     //SFTypeList    myTypes = { 'PICT' } ;
  291.     PicHandle    thePicture ;
  292.     OSErr        err = noErr;
  293.     short        theRef ;
  294.     // Variables added for carbon
  295.     NavDialogOptions    dialogOptions;
  296.     NavReplyRecord        reply;
  297.     AEDesc              defaultLocation;
  298.     AEKeyword           theKeyword;
  299.     DescType            actualType;
  300.     Size                actualSize;
  301.     FSSpec              documentFSSpec;
  302.     
  303.     //StandardFileReply    theSFReply ;
  304.  
  305.     menuID = HiWrd(menuResult);
  306.     menuItem = LoWrd(menuResult);
  307.     switch ( menuID ) {
  308.         case mApple:
  309.             switch ( menuItem ) {
  310.                 case iAbout:
  311.                     theDialog = GetNewDialog ( 128, nil, (WindowPtr)-1 );
  312.                     do {
  313.                         ModalDialog ( nil, &itemHit );
  314.                     } while( itemHit != ok ) ;
  315.                     DisposeDialog ( theDialog );
  316.                     break;
  317.                     
  318.                 default:
  319.                     // Desk Accessories not supported in carbon
  320.                     // They are automatically handled
  321.                     //GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
  322.                     //(void) OpenDeskAcc(daName);
  323.                     break;
  324.             }
  325.             break;
  326.         case mFile:
  327.             switch ( menuItem ) {
  328.                 case iOpen:
  329.                     /*
  330.                     // Get the file name to open
  331.                     StandardGetFile( nil, 1, myTypes, &theSFReply ) ;
  332.                     
  333.                     // did the user cancel?
  334.                     if(!theSFReply.sfGood)
  335.                         break ;
  336.                     
  337.                     // open the file
  338.                     err = FSpOpenDF( &theSFReply.sfFile, fsRdPerm, &theRef ) ;
  339.                     
  340.                     if( err != noErr )
  341.                         break ;     // should handle this properly
  342.                         
  343.                     thePicture = DoReadPICT( theRef, &err ) ;
  344.                     
  345.                     if( err != noErr )
  346.                         break ;     // should handle this properly
  347.                 
  348.                     // display the contents
  349.                     err = DoCreateWindow( thePicture ) ;
  350.                     */
  351.  
  352.     /*
  353.         The Standard File Package is no longer supported in Carbon.
  354.         Navigation services is to be used instead.  Above this comment
  355.         is the pre-carbon way of opening a dialog and selecting a file,
  356.         below is the carbon way.
  357.     */
  358.  
  359.                     /*OSErr NavGetFile (
  360.                                            AEDesc *defaultLocation, 
  361.                                            NavReplyRecord *reply, 
  362.                                         NavDialogOptions *dialogOptions, 
  363.                                         NavEventUPP eventProc, 
  364.                                         OSType fileType, 
  365.                                         OSType fileCreator, 
  366.                                         void *callBackUD );*/
  367.  
  368.                     // Create a "NavDialogOptions" and use defaults, but set
  369.                     // the directory to the app's directory
  370.                     NavGetDefaultDialogOptions(&dialogOptions);
  371.                     dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
  372.  
  373.                     AECreateDesc(typeFSS, &documentFSSpec,
  374.                              sizeof(documentFSSpec),
  375.                              &defaultLocation );
  376.  
  377.                     err = NavGetFile (&defaultLocation, &reply, &dialogOptions,
  378.                                 nil, nil, nil,
  379.                                 nil, nil);
  380.                     
  381.                     if (err != noErr || !reply.validRecord)
  382.                         break;
  383.  
  384.                     // Get a pointer to selected file
  385.                     err = AEGetNthPtr(&(reply.selection), 1,
  386.                                             typeFSS, &theKeyword,
  387.                                             &actualType,&documentFSSpec,
  388.                                             sizeof(documentFSSpec),
  389.                                             &actualSize);
  390.                     if (err != noErr)
  391.                         break;
  392.                     
  393.                     // open the file
  394.                     err = FSpOpenDF( &documentFSSpec, fsRdPerm, &theRef ) ;
  395.                     
  396.                     if( err != noErr )
  397.                         break ;     // should handle this properly
  398.                         
  399.                     thePicture = DoReadPICT( theRef, &err ) ;
  400.                     
  401.                     if( err != noErr )
  402.                         break ;     // should handle this properly
  403.                 
  404.                     // display the contents
  405.                     err = DoCreateWindow( thePicture ) ;
  406.  
  407.                     NavDisposeReply(&reply);
  408.                     AEDisposeDesc(&defaultLocation);
  409.                     
  410.                     break ;
  411.                     
  412.                 case iClose:
  413.                     DisposeWindow ( FrontWindow() );
  414.                     break ;
  415.                 case iQuit:
  416.                     gQuitFlag = true;
  417.                     break;
  418.             }
  419.             break;
  420.             
  421.         case mPalette:
  422.             switch ( menuItem ) {
  423.                 case iUsePictPalette :
  424.                     // toggle the check mark and the global boolean
  425.                     gUsePictPalette = !gUsePictPalette ;
  426.                     // For menus, use ActionMenuItem as opposed to ActionItem
  427.                     //CheckItem ( GetMenuHandle ( mPalette ), iUsePictPalette, gUsePictPalette );
  428.                     CheckMenuItem ( GetMenuHandle (mPalette), iUsePictPalette, gUsePictPalette );
  429.                     break ;
  430.             }
  431.             break ;
  432.             
  433.         case mTest:
  434.         
  435. //--------------------------- T E S T   R O U T I N E ---------------------------------
  436.             if( menuItem == 1 ) {
  437.                 // get some of the screen
  438.                 void ShrinkToBWPict( WindowPtr theWindow ) ;        // prototype
  439.                 
  440.                 // because I have multiple monitors and I wanted to test on them
  441.                 // I set up the area below, you may want something rather different
  442.                 // YOU WILL PROBABLY NEED TO CHANGE THIS
  443.                 
  444.                 Rect area = { 0, -50, 200, 200 } ;                // area to save 
  445.  
  446.                 ShrinkToBWPict( FrontWindow() ) ;
  447.                 
  448.                 
  449. //--------------------------- T E S T   R O U T I N E ---------------------------------
  450.  
  451.             }
  452.             break; 
  453.  
  454.     }
  455.     HiliteMenu(0);        // Unhighlight whatever MenuSelect or MenuKey hilited
  456. }
  457.  
  458. void AdjustMenus( void ) 
  459. {
  460.     WindowPtr    theWindow ;
  461.     theWindow = FrontWindow() ;
  462.     if( theWindow != nil ) {
  463.         // In carbon use ActionMenuItem instead of ActionItem
  464.         //EnableItem ( GetMenuHandle ( mFile ), iClose );
  465.         //EnableItem ( GetMenuHandle ( mTest ), 0 );    // <== 0 is entire menu
  466.         EnableMenuItem ( GetMenuHandle ( mFile ), iClose );
  467.         EnableMenuItem ( GetMenuHandle ( mTest ), 0 );    // <== 0 is entire menu
  468.     }
  469.     else {
  470.         // In carbon use ActionMenuItem instead of ActionItem
  471.         //DisableItem ( GetMenuHandle ( mFile ), iClose );
  472.         //DisableItem ( GetMenuHandle ( mTest ), 0 );    // <== 0 is entire menu
  473.         DisableMenuItem ( GetMenuHandle ( mFile ), iClose );
  474.         DisableMenuItem ( GetMenuHandle ( mTest ), 0 );    // <== 0 is entire menu
  475.     }
  476.     // make sure the check marks are correct
  477.     // Again, use ActionMenuItem instead of ActionItem
  478.     //CheckItem ( GetMenuHandle ( mPalette ), iUsePictPalette, gUsePictPalette );
  479.     CheckMenuItem ( GetMenuHandle ( mPalette ), iUsePictPalette, gUsePictPalette );
  480. }
  481.  
  482. PicHandle DoReadPICT( short theRef, OSErr *theErr ) 
  483. {
  484.     long        theFileSize ;
  485.     PicHandle    thePicture ;
  486.     
  487.     // pict files have a 512 byte header at the front - we dont care about this
  488.     // we can find the size of the pict by subtracting 512 bytes from the length
  489.     // of the file.  We then want to resize the handle to that and read the data
  490.     // into the resized handle.
  491.     
  492.     if(( *theErr = GetEOF( theRef, &theFileSize )) != noErr ) {
  493.         FSClose( theRef ) ;
  494.         return nil ; 
  495.     }
  496.     
  497.     if(( *theErr = SetFPos( theRef, fsFromStart, 512)) != noErr ) {
  498.         FSClose( theRef ) ;
  499.         return nil ; 
  500.     }
  501.  
  502.     theFileSize -= 512 ;
  503.     
  504.     thePicture = (PicHandle)NewHandle( theFileSize ) ;
  505.     if( thePicture == nil ) {
  506.         FSClose( theRef ) ;
  507.         *theErr = MemError() ;
  508.         return nil ;         // what ever the mem manager error was
  509.     }
  510.     
  511.     HLock( (Handle)thePicture ) ;
  512.     *theErr = FSRead( theRef, &theFileSize, (Ptr)*thePicture ) ;
  513.     HUnlock(  (Handle)thePicture ) ;
  514.     
  515.     if( *theErr != noErr ) {
  516.         FSClose( theRef ) ;
  517.         return nil ; 
  518.     }
  519.  
  520.     return thePicture ;    
  521. }
  522.  
  523. OSErr DoCreateWindow( PicHandle thePicture )
  524. {
  525.  
  526.     Rect        theRect ;
  527.     OSErr        theErr ;
  528.     GWorldPtr    theNewWorld ;
  529.     CGrafPtr    savedPort ;
  530.     WindowPtr    theWindow ;
  531.     GDHandle    oldDevice ;
  532.     
  533.     PictInfo        thePictInfo ;
  534.     PaletteHandle    thePictPalette = nil ;
  535.     CTabHandle        thePictCTab = nil ;
  536.     
  537.     // make an offscreen environment and image the pict into this
  538.     // Make a window the size of the pict
  539.     // store a reference to the GWorld in the Refcon of the window
  540.     // invalidate the window content area.
  541.     
  542.     theRect = (**thePicture).picFrame;
  543.     
  544.     // to we want to attempt to sample the picture... 
  545.     if( gUsePictPalette ) {
  546.     
  547.         // use the picture utilities to get the palette for the window
  548.         theErr = GetPictInfo( thePicture, &thePictInfo, returnColorTable, 256, systemMethod, 0) ;
  549.         
  550.         // set up the palette and color table for later use
  551.         thePictPalette = NewPalette( 256, thePictInfo.theColorTable, pmTolerant, 0x1000 ) ;
  552.         thePictCTab = thePictInfo.theColorTable ;
  553.     }
  554.     
  555.     // we are only dealing with eight bit images here
  556.     // hence the requirement for the picture utils package to 
  557.     // return 256 colors, and we will create a gWorld 8 bits deep
  558.     
  559.     theErr = NewGWorld( &theNewWorld, 8, &theRect, thePictCTab, nil, 0L ) ;
  560.     
  561.     if( theErr != noErr ) 
  562.         return theErr ;
  563.     
  564.     // save the world
  565.     GetGWorld( &savedPort, &oldDevice ) ;
  566.     SetGWorld( theNewWorld, nil ) ;
  567.     
  568.     
  569.     RGBForeColor( &kRGBBlack ) ;        // ensure the fg and bg colors are 
  570.     RGBBackColor( &kRGBWhite ) ;        // as anticipated
  571.     EraseRect( &theRect ) ;                // clear the area for the pict
  572.     PenMode( srcCopy ) ;                // ensure the t/f mode is as expected
  573.  
  574.     SetOrigin( theRect.left, theRect.top );
  575.  
  576.     
  577.     // render the image into the offscreen buffer
  578.     DrawPicture( thePicture, &theRect ) ;
  579.     SetOrigin( 0, 0 );
  580.     
  581.     SetGWorld( savedPort, oldDevice ) ;
  582.     
  583.     // create the window
  584.     OffsetRect( &theRect, gStaggerPos.h, gStaggerPos.v) ;
  585.     gStaggerPos.h += 16 ;
  586.     gStaggerPos.v += 16 ;        // heh - should roll these around, but you wont 
  587.                                 // create more than a couple of windows, will you  :-)
  588.                                  
  589.     theWindow  = NewCWindow( nil, &theRect, "\pplayTime", true, 
  590.                                 documentProc, (WindowPtr)-1, true, (long)theNewWorld );    
  591.                 
  592.     // and if we set up the palette earlier assign it to the window                
  593.     if( thePictPalette != nil ) {
  594.         SetPalette ( theWindow, thePictPalette, true );
  595.     }
  596.     
  597.     ActivatePalette ( theWindow );    
  598.     
  599.     // make sure it is visible
  600.     ShowWindow( theWindow ) ;
  601.     
  602.     SetGWorld( (CGrafPtr)theWindow, nil ) ;
  603.     
  604.     // invalidate the content region of the window - we don't do any drawing to it here.
  605.     // Not supported in carbon
  606.     //InvalRect ( &theRect );
  607.     InvalWindowRect ( theWindow, &theRect );
  608.     
  609.     SetGWorld( savedPort, oldDevice ) ;
  610.     return noErr;
  611. }